#include <stdio.h>
#include <stdlib.h>
#include <cjson/cJSON.h>
#include "http.h"
#include "auth.h"

char* ak = "API Key";
char* sk = "Secret Key";

//从文件中读取音频数据
//file: 文件名
//buf:  缓冲区指针的地址
//return: 读取数据大小
size_t load_file(char* file, char** buf)
{
    FILE* fp = fopen(file, "r");
    if (!fp)
    {
        perror("fopen");
        return 0;
    }

    //获取文件大小
    if (fseek(fp, 0, SEEK_END) < 0)
    {
        perror("fseek");
        fclose(fp);
        return 0;
    }

    long size = ftell(fp);
    if (size < 0)
    {
        perror("ftell");
        fclose(fp);
        return 0;
    }

    //分配缓冲区，并将文件中的数据读入到缓冲区中
    *buf = malloc(size);
    if (!*buf)
    {
        perror("malloc");
        fclose(fp);
        return 0;
    }

    //将文件指针移动到文件头
    fseek(fp, 0, SEEK_SET);

    size_t readn = fread(*buf, 1, size, fp);
    if (readn != size)
    {
        fprintf(stderr, "file size: %ld, read: %zd\n", size, readn);
    }

    fclose(fp);

    return readn;
}

//发送HTTP请求报文，并返回服务器响应报文
//token: 访问API需要的access token
//audio: 需要转换的音频数据
//size:  音频数据的大小
//return: 服务器返回的响应报文
char* send_request(char* token, char* audio, size_t size)
{
    //设置API地址和参数
    char* url = NULL;
    asprintf(&url, "http://vop.baidu.com/server_api?dev_pid=1537&cuid=liuyu&token=%s", token);

    //增加请求头部字段
    struct curl_slist* headers = NULL;
    headers = curl_slist_append(headers, "Content-Type: audio/pcm;rate=16000");

    //发送请求消息
    char* response = post(url, headers, audio, &size);
    free(url);
    curl_slist_free_all(headers);

    if (!response)
    {
        return NULL;
    }

    return response;
}

//解析服务器响应报文，打印识别结果
void process_response(char* respdata)
{
    //解析json
    cJSON* root = cJSON_Parse(respdata);
    if (!root)
    {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL)
        {
            fprintf(stderr, "Error before: %s\n", error_ptr);
        }
        return;
    }

    //获取错误码
    cJSON* err_no = cJSON_GetObjectItem(root, "err_no");
    if (!err_no)
    {
        fprintf(stderr, "err_no attribute not found\n");
        cJSON_Delete(root);
        return;
    }

    if (err_no->valueint != 0)
    {
        cJSON* err_msg = cJSON_GetObjectItem(root, "err_msg");
        if (err_msg)
        {
            fprintf(stderr, "Error: %s\n", err_msg->valuestring);
        }
        cJSON_Delete(root);
        return;
    }

    //获取转换结果
    cJSON* result = cJSON_GetObjectItem(root, "result");
    if (!result)
    {
        fprintf(stderr, "result attribute not found\n");
        cJSON_Delete(root);
        return;
    }

    if (!cJSON_IsArray(result))
    {
        fprintf(stderr, "result attribute format error\n");
        cJSON_Delete(root);
        return;
    }

    int n = cJSON_GetArraySize(result);
    for (int i = 0; i < n; i++)
    {
        cJSON* item = cJSON_GetArrayItem(result, i);
        puts(item->valuestring);
    }

    cJSON_Delete(root);
}

int main(int argc, char** argv)
{
    char* token = get_token(ak, sk);
    if (!token)
    {
        return EXIT_FAILURE;
    }

    char* audio = NULL;
    size_t size = load_file(argv[1], &audio);
    if (!size)
    {
        free(token);
        return EXIT_FAILURE;
    }
    char* response = send_request(token, audio, size);
    free(audio);
    free(token);
    if (!response)
    {
        return EXIT_FAILURE;
    }
    process_response(response);
    free(response);
    return 0;
}
